/**
 * 问卷项目i18n插件
 * @author 贾迎博
 * @description
 * 问卷项目i18n插件
 * @todo

 */

(function (global, factory) {
    global = global || self;
    global.i18n = factory();
}(this, function () {
    'use strict';

    /** 配置 */
    var Config = {
        /** 默认语言 */
        defaultLang: 'en',
        /** 当前语言 */
        lang: undefined,
        /** 是否自动获取语言类型 */
        autoGetLangType: true,
        /** 语言源 */
        resource: undefined,
        /**
         * 回调函数
         * @returns {String} langType:当前语言
        */
        callback: undefined,
    };

    /**
     * 一些工具类
     */
    var Util = {
        /**
         * 合并对象
         * @param {*} obj1
         * @param {*} obj2
         * @returns obj1
         */
        assignObj: function (obj1, obj2) {
            for (var key in obj2) {
                obj1[key] = obj2[key];
            }
            return obj1;
        },
        /**
         * 获取地址栏参数
         * @param {*} name 参数名
         */
        getQueryString: function (name) {
            var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)'),
                search = decodeURIComponent(window.location.search.substr(1)),
                r = search.match(reg);
            return r != null ? r[2] : null;
        },
        /**
         * @param {*} val 数组
         * @param {*} cb 循环中执行
         */
        loop: function (val, cb) {
            for (var i = 0, len = val.length; i < len; i++) {
                cb && cb(i, val[i])
            }
        }
    }

    /**
     * dom树加载完毕事件
     * @param {*} callback
     */
    document.ready = function (callback) {
        ///兼容FF,Google
        if (document.addEventListener) {
            function DOMContentLoaded() {
                document.removeEventListener('DOMContentLoaded', DOMContentLoaded, false);
                callback();
            }
            document.addEventListener('DOMContentLoaded', DOMContentLoaded, false)
        }
        //兼容IE
        else if (document.attachEvent) {
            function onreadystatechange() {
                if (document.readyState == "compvare") {
                    document.detachEvent("onreadystatechange", onreadystatechange);
                    callback();
                }
            }
            document.attachEvent('onreadystatechange', onreadystatechange)
        }
        else if (document.lastChild == document.body) {
            callback();
        }
    }

    /**
     * 获取数据源
     */
    var GetResource = function () {
        if (!Config.resource) console.error('resource值为：' + Config.resource + '，请检查！');
        if (!Config.resource[Config.lang]) {
            Config.lang = Config.defaultLang;
            console.error('resource中没有获取到对应的语种！已使用默认语种。当前传入lang:' + Config.lang);
        }

        Util.assignObj(i18n.__proto__, Config.resource[Config.lang])
    }

    /**
     * 获取语种
     * 优先级如下：
     * 1.init传入，
     * 2.地址栏传入，
     * 3.自动获取浏览器语言(通过Config.autoGetLangType开关)，
     * 4.默认语言。
     */
    var GetLangType = {
        /**
         * 获取浏览器语言
         * @returns lang
         */
        getUrlLang: function () {
            return Util.getQueryString('lang')
        },
        /**
         * 获取地址栏传入的语种参数
         * @returns lang
         */
        getBrowserLang: function () {
            var browserLang = navigator.language.toLowerCase(), lang = undefined;

            lang = browserLang;
            if (browserLang.indexOf('zh') != -1) { // 区分简繁体中文 繁体一律以zh-tw代指
                lang = browserLang != "zh-cn" ? "zh-tw" : "zh-cn"
            }

            if (browserLang.indexOf('en') != -1) { // 英文区(en-us en-nz)一律显示英文
                lang = "en";
            }

            return lang;
        },
        run: function () {
            if (Config.lang) return;

            Config.lang = this.getUrlLang() || (Config.autoGetLangType && this.getBrowserLang()) || Config.defaultLang;

            Config.callback && Config.callback(Config.lang);
        }

    }

    /**
     * 渲染器
     */
    var Render = {
        interReg: /\{\{(.*)\}\}/g,
        /**
         * 处理插值语法
         * @param {*} node 元素节点
         * @returns 虚拟DOM
         */
        processInter: function (node) {
            // 创建文本代码片段 存储虚拟DOM(在程序的内存中比较) 虚拟DOM很小
            var fragment = document.createDocumentFragment();
            var child;
            // 第一个子节点
            while (child = node.firstChild) {
                Render.renderText(child)
                fragment.appendChild(child)
            }
            return fragment
        },
        /**
         * 渲染插值语法
         * @param {*} node
         */
        renderText: function (node) {
            switch (node.nodeType) {
                // 元素节点
                case 1:
                    node.append(Render.processInter(node));
                    break;
                // 文本节点
                case 3:
                    if (Render.interReg.test(node.nodeValue)) {
                        // 获取正则匹配的数据
                        node.nodeValue = node.nodeValue.replace(Render.interReg, function ($1) {
                            var val = eval($1),
                                parentEle = node.parentNode;

                            // 实现\n换行但不影响子元素
                            if (val && val.indexOf('\n') != -1) {
                                parentEle.style.whiteSpace = 'pre-line';
                                Util.loop(parentEle.children, function (i, v) {
                                    v.style.whiteSpace = 'normal';
                                })
                            }

                            return val ? val : '';

                        })
                    }
                    break;
                default:

                    break;
            }
        },
        /**
         * 处理指令语法
         */
        processAttr: function () {
            Util.loop(Object.keys(Render.order), function (i, v) {
                Util.loop(document.querySelectorAll('[i18n-' + v + ']'), function (j, k) {
                    Render.order[v](k);
                })
            })
        },
        /**
         * 指令集
         */
        order: {
            /**
             * 根据元素的文本内容来控制元素是否显示
             * 对存在子元素的节点不生效
             * @param {*} node 元素
             */
            show: function (node) {
                if (node.children.length) return;
                if (!node.innerText || node.innerText == 'undefined' || node.innerText == 'null') {
                    node.remove();
                }
            }
        },
        run: function () {
            document.ready(function () {
                if (!Config.resource[Config.lang]) return;

                document.head.append(Render.processInter(document.head));
                document.body.append(Render.processInter(document.body));

                Render.processAttr();
            })
        }
    }

    /** 初始化 */
    var init = function (ops) {
        Util.assignObj(Config, ops);

        GetLangType.run();
        GetResource();
        Render.run();
    };

    /**
     * 组合API
     */
    function initGlobalAPI(i18n) {
        i18n.__proto__.config = Config;
        i18n.__proto__.init = init;
        i18n.__proto__.GetLangType = GetLangType;
    }

    function i18n() { };

    initGlobalAPI(i18n);

    return i18n;
}))
